/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.qubuyer.core.http;

import com.google.gson.Gson;
import com.google.gson.JsonIOException;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import okhttp3.ResponseBody;
import retrofit2.Converter;

final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private final Gson gson;
    private Type type;
    private final TypeAdapter<T> adapter;

    GsonResponseBodyConverter(Gson gson, Type type, TypeAdapter<T> adapter) {
        this.gson = gson;
        this.type = type;
        this.adapter = adapter;
    }

    @Override
    public T convert(ResponseBody value) throws IOException {
        if (type instanceof ParameterizedType) {
            Type rowType = ((ParameterizedType) this.type).getRawType();
            if (rowType instanceof Class) {
                if (((Class<?>) rowType).getName().equals("com.qubuyer.core.http.HttpResult")) {
                    Type argument = ((ParameterizedType) type).getActualTypeArguments()[0];
                    if (argument instanceof Class) {
                        try {
                            String json = value.string();
                            if (!((Class<?>) argument).isArray() && json.contains("\"data\":[]")) {
                                json = json.replace("\"data\":[]", "\"data\":{}");
                            }
                            if(argument == String.class){
                                json = json.replace("\"data\":[]", "\"data\":\"\"");
                                json = json.replace("\"data\":{}", "\"data\":\"\"");
                            }
                            if(argument == Integer.class){
                                json = json.replace("\"data\":[]", "\"data\":0");
                                json = json.replace("\"data\":{}", "\"data\":0");
                                json = json.replace("\"data\":\"\"", "\"data\":0");
                            }
                            if(argument == Float.class){
                                json = json.replace("\"data\":[]", "\"data\":0.0");
                                json = json.replace("\"data\":{}", "\"data\":0.0");
                                json = json.replace("\"data\":\"\"", "\"data\":0.0");
                            }
                            if(argument == Double.class){
                                json = json.replace("\"data\":[]", "\"data\":0.0");
                                json = json.replace("\"data\":{}", "\"data\":0.0");
                                json = json.replace("\"data\":\"\"", "\"data\":0.0");
                            }
                            return gson.fromJson(json, TypeToken.get(type).getType());
                        } finally {
                            value.close();
                        }
                    }
                }
            }
        }
        JsonReader jsonReader = gson.newJsonReader(value.charStream());
        try {
            T result = adapter.read(jsonReader);
            if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
                throw new JsonIOException("JSON document was not fully consumed.");
            }
            return result;
        } finally {
            value.close();
        }
    }
}
